package edu.moravian.utilities;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author ronaghan
 *
 * This class represents a general way to read in data from files so that
 * multiple unstandardized methods don't crop up.
 * 
 * If any errors occur with the file reader, it currently just throws them up
 * 
 */
public class FileReader
{
    //Use a line number reader so we can report lines numbers that errors occured on to users 
    LineNumberReader in;
    
    //the currentline of input
    String curLine;
    
    //the current line of input split
    String[] curSplitline;
    
    //A list of the identifiers and variables extracted from the file 
    List<String> identifiers;
    List<String> variables;
    
    //the current identifier/variable being examined
    int curVarIDNum;
    
    //the name of the file 
    String filename;
    
    //the list of comment identifiers
    private static final List<String> commentList;

    static
    {
        //current comment lines start with a pound or are 
        //      /*
        //       *                                             
        //       */
        //
        // or even the //
        commentList = new ArrayList<String>();
        commentList.add("#");
        commentList.add("/*");
        commentList.add("*");
        commentList.add("*/");
        commentList.add("//");
    }




    /**
     * Create a new file reader based on the specified file name
     * This will check for errors in the file and ensure that there are
     * two items on each line (The identifier for the line and the variable)
     *
     * @param filename
     *
     * @throws FileNotFoundException
     * @throws IOException
     */
    @SuppressWarnings("CallToThreadDumpStack")
    public FileReader(String filename) throws FileNotFoundException, IOException 
    {
       
        this.filename = filename;
        in = new LineNumberReader(new java.io.FileReader(filename));

        identifiers = new ArrayList<String>();
        variables = new ArrayList<String>();

        curVarIDNum = 0;
        String line;
        String splitLine[];

        //while we have more input
        while (in.ready())
        {
            //read in the next line 
            line = in.readLine().trim();

            if (line.isEmpty() || isComment(line))
            {
                //ignore comments and blank lines
            }
            else
            {
                //split the line based on spaces
                splitLine = line.split("\\s+");

                //ensure that each line of input has two strings on it
                if (splitLine.length > 2)
                {
                    throw new IllegalStateException("While reading in the file: " + filename + " there was an error at line: " + in.getLineNumber() + ""
                            + ". There was more than a single identifier and variable");
                }
                else if (splitLine.length < 2)
                {
                    throw new IllegalStateException("While reading in the file: " + filename + " there was an error at line: " + in.getLineNumber() + ""
                            + ". Expected and identifier and a variable but one or more was missing");
                }
                else
                {

                    //add to the ID and variables lists
                    identifiers.add(splitLine[0]);
                    variables.add(splitLine[1]);
                }

            }
        }

        //close the reader, we don't need it anymore since the ids and vars are stored in the appropriate arrays 
        in.close();
        
      
        

    }




    //helper method to weed out lines that are comment 
    private boolean isComment(String line)
    {
        for (String commentIdentifier : commentList)
        {
            if (line.startsWith(commentIdentifier))
            {
                return true;
            }
        }
        return false;
    }



    /**
     * Gets the next identifier (The identifier at the ID/Var counter)
     * 
     * This method does not advance the ID/Var counter, getNextVariable does
     * 
     * @return the string representation of the current identifier
     */
    public String nextIdentifier()
    {
        if (curVarIDNum >= variables.size())
        {
            throw new IllegalStateException("Tried to read in identifier " + curVarIDNum + " but there are only " + identifiers.size() + " identifiers in the file: " + filename);
        }
        
        return identifiers.get(curVarIDNum);
    }




    /**
     * Gets the next varialbe (The variable at the ID/Var counter)
     * 
     * This method advances the ID/Var counter. It is expected that either just next
     * variable will be used and the ids will be ignored or the ids will be checked, then 
     * the variable will be gotten and so on. 
     * 
     * @return string representation of the current variable
     */
    public String nextVariable()
    {
        if (curVarIDNum >= variables.size())
        {
            throw new IllegalStateException("Tried to read in variable " + curVarIDNum + " but there are only " + identifiers.size() + " variables in the file: " + filename);
        }
        
        String ret = variables.get(curVarIDNum);
        curVarIDNum++;
        return ret;
    }




    /**
     * Method to ensure that there are more Identifiers/variables to extract
     * 
     * @return true if there are additional variables, false otherwise 
     */
    public boolean hasNextLine()
    {
        if (curVarIDNum + 1 < variables.size())
        {
            return true;
        }
        else
        {
            return false;
        }
    }




}

